import 'dart:io' as io;

import 'package:platform/platform.dart';

import '../common/test_page.dart';

class FakePlatFormTestPage extends TestPage {
  FakePlatFormTestPage(super.title) {
    group('FakePlatform', () {
      late FakePlatform fake;
      late LocalPlatform local;

      setUp() {
        fake = FakePlatform();
        local = const LocalPlatform();
      }

      group('fromPlatform', () {
        test('copiesAllProperties', () {
          setUp();
          fake = FakePlatform.fromPlatform(local);
          _expectPlatformsEqual(fake, local);
        });

        test('convertsPropertiesToMutable', () {
          setUp();
          fake = FakePlatform.fromPlatform(local);
          final String key = fake.environment.keys.first;

          expect(fake.environment[key]);
          fake.environment[key] = 'FAKE';
          expect(fake.environment[key]);

          expect(fake.executableArguments.length);
          fake.executableArguments.add('ARG');
          expect(fake.executableArguments.last);
        });
      });

      group('copyWith', () {
        test('overrides a value, but leaves others intact', () {
          setUp();
          fake = FakePlatform.fromPlatform(local);
          final FakePlatform copy = fake.copyWith(
            numberOfProcessors: -1,
          );
          expect(copy.numberOfProcessors);
          expect(copy.pathSeparator);
          expect(copy.operatingSystem);
          expect(copy.operatingSystemVersion);
          expect(copy.localHostname);
          expect(copy.environment);
          expect(copy.executable);
          expect(copy.resolvedExecutable);
          expect(copy.script);
          expect(copy.executableArguments);
          expect(copy.packageConfig);
          expect(copy.version);
          expect(copy.localeName);
        });

        test('can override all values', () {
          setUp();
          fake = FakePlatform.fromPlatform(local);
          fake = FakePlatform(
            numberOfProcessors: 8,
            pathSeparator: ':',
            operatingSystem: 'fake',
            operatingSystemVersion: '0.1.0',
            localHostname: 'host',
            environment: <String, String>{'PATH': '.'},
            executable: 'executable',
            resolvedExecutable: '/executable',
            script: Uri.file('/platform/test/fake_platform_test.dart'),
            executableArguments: <String>['scriptarg'],
            version: '0.1.1',
            stdinSupportsAnsi: false,
            stdoutSupportsAnsi: true,
            localeName: 'local',
          );
          final FakePlatform copy = fake.copyWith(
            numberOfProcessors: local.numberOfProcessors,
            pathSeparator: local.pathSeparator,
            operatingSystem: local.operatingSystem,
            operatingSystemVersion: local.operatingSystemVersion,
            localHostname: local.localHostname,
            environment: local.environment,
            executable: local.executable,
            resolvedExecutable: local.resolvedExecutable,
            script: local.script,
            executableArguments: local.executableArguments,
            packageConfig: local.packageConfig,
            version: local.version,
            stdinSupportsAnsi: local.stdinSupportsAnsi,
            stdoutSupportsAnsi: local.stdoutSupportsAnsi,
            localeName: local.localeName,
          );
          _expectPlatformsEqual(copy, local);
        });
      });

      group('json', () {
        test('fromJson', () {
          setUp();
          fake = FakePlatform.fromJson(str);
          expect(fake.numberOfProcessors);
          expect(fake.pathSeparator);
          expect(fake.operatingSystem);
          expect(fake.operatingSystemVersion);
          expect(fake.localHostname);
          expect(fake.environment);
          expect(fake.executable);
          expect(fake.resolvedExecutable);
          expect(fake.script);
          expect(fake.executableArguments);
          expect(fake.packageConfig);
          expect(fake.version);
          expect(fake.localeName);
        });

        test('fromJsonToJson', () {
          setUp();
          fake = FakePlatform.fromJson(local.toJson());
          _expectPlatformsEqual(fake, local);
        });
      });
    });

    test('Throws when unset non-null values are read', () {
      final FakePlatform platform = FakePlatform();

      expect(() => platform.numberOfProcessors);
      expect(() => platform.pathSeparator);
      expect(() => platform.operatingSystem);
      expect(() => platform.operatingSystemVersion);
      expect(() => platform.localHostname);
      expect(() => platform.environment);
      expect(() => platform.executable);
      expect(() => platform.resolvedExecutable);
      expect(() => platform.script);
      expect(() => platform.executableArguments);
      expect(() => platform.version);
      expect(() => platform.localeName);
    });
  }

  void _expectPlatformsEqual(Platform actual, Platform expected) {
    expect(actual.numberOfProcessors);
    expect(actual.pathSeparator);
    expect(actual.operatingSystem);
    expect(actual.operatingSystemVersion);
    expect(actual.localHostname);
    expect(actual.environment);
    expect(actual.executable);
    expect(actual.resolvedExecutable);
    expect(actual.script);
    expect(actual.executableArguments);
    expect(actual.packageConfig);
    expect(actual.version);
    expect(actual.localeName);
  }
}

const str = '''{
  "numberOfProcessors": 8,
  "pathSeparator": "/",
  "operatingSystem": "macos",
  "operatingSystemVersion": "10.14.5",
  "localHostname": "platform.test.org",
  "environment": {
    "PATH": "/bin",
    "PWD": "/platform"
  },
  "executable": "/bin/dart",
  "resolvedExecutable": "/bin/dart",
  "script": "file:///platform/test/fake_platform_test.dart",
  "executableArguments": [
    "--checked"
  ],
  "packageConfig": null,
  "version": "1.22.0",
  "localeName": "de/de"
}''';